<template>
    <view
        class="checkbox flex-inline align-center"
        :class="[classes, labelPosition1]"
        :style="[
            styles,
            {
                width: type1 !== 'btn' ? getSize(width1).styles : ''
            }
        ]"
        @click="handleClick()"
    >
        <block v-if="type1 !== 'btn'">
            <view
                :class="[
                    colorClass2,
                    bgColorClass2,
                    borderClass,
                    {
                        disabled: disabled1,
                        solid: !checked1 && (type1 === 'df' || type1 === 'hollow') && !bgColorClass,
                        sm: size1 === 'sm'
                    }
                ]"
                :style="{
                    color: colorStyle2,
                    backgroundColor: bgColorStyle2,
                    borderColor: borderStyle
                }"
                class="cbx flex-inline align-center justify-center"
            >
                <uxt-icon type="check" v-if="checked1"></uxt-icon>
            </view>
            <view v-if="label" class="label flex-sub">{{ label }}</view>
        </block>
        <view
            v-else
            class="padding-xs radius btn"
            :class="[
                colorClass2,
                bgColorClass2,
                {
                    disabled: disabled1,
                    sm: size1 === 'sm'
                }
            ]"
            :style="{
                color: colorStyle2,
                backgroundColor: bgColorStyle2
            }"
        >
            {{ label }}
        </view>
    </view>
</template>

<script>
import { deepCopy } from '../utils/util.js'
import baseMixin from '../mixins/base.js'
import formMixin from '../mixins/form.js'
import uxtIcon from './uxt-icon.vue'

export default {
    name: 'uxt-checkbox',
    mixins: [baseMixin, formMixin],
    components: {
        uxtIcon
    },
    props: {
        // 样式
        type: {
            type: String,
            default: 'df',
            validator(value) {
                return ['df', 'hollow', 'onlyicon', 'btn'].includes(value)
            }
        },
        // 大小, ''/'sm'
        size: {
            type: String,
            default: 'df',
            validator(value) {
                return ['df', 'sm'].includes(value)
            }
        },
        // 是否选中
        checked: {
            type: Boolean,
            default: false
        },
        // 宽度
        width: {
            type: [Number, String]
        },
        // 标签
        label: {
            type: String
        },
        // 标签位置 left/right
        labelPosition: {
            type: String,
            default: 'right',
            validator(value) {
                return ['left', 'right'].includes(value)
            }
        }
    },
    data() {
        return {
            checked1: this.getChecked(),
            width1: this.width,
            labelPosition1: this.labelPosition,
            type1: this.type,
            size1: this.size,
            disabled1: this.disabled
        }
    },
    inject: {
        groupId: {
            default: 0
        },
        groupVModel: {
            default: false
        }
    },
    computed: {
        colorClass2() {
            let ret = ''
            switch (this.type1) {
                case 'df':
                case 'onlyicon':
                case 'btn':
                    ret = this.checked1 ? this.colorClass : ''
                    break
                case 'hollow':
                    ret = this.checked1
                        ? this.bgColorClass
                              .replace('gradual-', '')
                              .replace('light-', '')
                              .replace('bg-', 'text-')
                        : ''
                    break
            }
            return ret
        },
        colorStyle2() {
            let ret = ''
            switch (this.type1) {
                case 'df':
                case 'onlyicon':
                case 'btn':
                    ret = this.checked1 ? this.colorStyle : ''
                    break
                case 'hollow':
                    ret = this.checked1 ? this.bgColorStyle : ''
                    break
            }
            return ret
        },
        bgColorClass2() {
            let ret = ''
            switch (this.type1) {
                case 'df':
                    ret = this.checked1 ? this.bgColorClass : ''
                    break
                case 'btn':
                    ret = this.checked1 ? this.bgColorClass : 'bg-grey'
                    break
            }
            return ret
        },
        bgColorStyle2() {
            let ret = ''
            switch (this.type1) {
                case 'df':
                case 'btn':
                    ret = this.checked1 ? this.bgColorStyle : ''
                    break
            }
            return ret
        },
        borderClass() {
            let ret = ''
            switch (this.type1) {
                case 'df':
                    ret = this.checked1
                        ? ''
                        : this.bgColorClass
                              .replace('gradual-', '')
                              .replace('light-', '')
                              .replace('bg-', 'solid-')
                    break
                case 'hollow':
                    ret = this.bgColorClass
                        .replace('gradual-', '')
                        .replace('light-', '')
                        .replace('bg-', 'solid-')
                    break
            }
            return ret
        },
        borderStyle() {
            let ret = ''
            switch (this.type1) {
                case 'df':
                    ret = this.checked1 ? '' : this.bgColorStyle
                    break
                case 'hollow':
                    ret = this.bgColorStyle
                    break
            }
            return ret
        }
    },
    watch: {
        checked(newVal, oldVal) {
            // v-model绑定时忽略checked
            if (this.mode().endsWith('VModel')) {
                return
            }
            this.checked1 = newVal
            this.emitGroupChange()
            this.value1 = this.getValue()
        },
        value(newVal, oldVal) {
            this.checked1 = this.getChecked()
            this.emitGroupChange()
            this.value1 = this.getValue()
        },
        // checked1(newVal, oldVal) {
        //     this.emitGroupChange()
        // },
        width(newVal, oldVal) {
            this.width1 = newVal
        },
        labelPosition(newVal, oldVal) {
            !this.groupId && (this.labelPosition1 = newVal)
        },
        type(newVal, oldVal) {
            !this.groupId && (this.type1 = newVal)
        },
        size(newVal, oldVal) {
            !this.groupId && (this.size1 = newVal)
        },
        disabled(newVal, oldVal) {
            !this.groupId && (this.disabled1 = newVal)
        }
    },
    methods: {
        // 4种模式
        mode() {
            if (this.groupId) {
                if (this.groupVModel) {
                    return 'groupVModel'
                }
                return 'group'
            }
            if (typeof this.value === 'undefined') {
                return 'single'
            }
            if (typeof this.value === 'boolean') {
                return 'singleVModel'
            }
            throw new Error('非法使用radio')
        },
        getValue() {
            switch (this.mode()) {
                case 'group':
                case 'groupVModel':
                    return this.value
                default:
                    return this.checked1
            }
        },
        getChecked() {
            switch (this.mode()) {
                case 'group':
                case 'single':
                    return this.checked
                case 'singleVModel':
                    return this.value
                default:
                    return false
            }
        },
        handleClick(reset = false) {
            if (!this.disabled1 || reset) {
                this.checked1 = !this.checked1
                if (!reset) {
                    this.emitGroupChange()
                }
                this.value1 = this.getValue()
                this.$emit('change', { detail: { checked: this.checked1, value: this.value1 } })
                this.$emit('input', this.value1)
            }
        },
        emitGroupChange(isInit = false) {
            let emitName = 'groupchange'
            if (isInit) {
                emitName = 'groupinit'
            }
            this.groupId &&
                uni.$emit(`${emitName}.${this.groupId}`, {
                    checked: this.checked1,
                    value: this.getValue()
                })
        },
        reset(value) {
            if ((value && !this.checked1) || (!value && this.checked1)) {
                this.handleClick(true)
            }
        }
    },
    created() {
        if (this.groupId) {
            uni.$on(`groupreset.${this.groupId}`, res => {
                if (
                    Array.isArray(res) &&
                    ((res.includes(this.value1) && !this.checked1) ||
                        (!res.includes(this.value1) && this.checked1))
                ) {
                    this.handleClick(true)
                }
            })
            uni.$on(`provide.width.${this.groupId}`, res => {
                !this.width && (this.width1 = res)
            })
            uni.$on(`provide.labelPosition.${this.groupId}`, res => {
                this.labelPosition1 = res
            })
            uni.$on(`provide.type.${this.groupId}`, res => {
                this.type1 = res
            })
            uni.$on(`provide.size.${this.groupId}`, res => {
                this.size1 = res
            })
            uni.$on(`provide.disabled.${this.groupId}`, res => {
                this.disabled1 = res
            })
        }
    },
    mounted() {
        !this.groupVModel && this.emitGroupChange(true)
    },
    destroyed() {
        if (this.groupId) {
            uni.$off(`groupreset.${this.groupId}`)
            uni.$off(`provide.width.${this.groupId}`)
            uni.$off(`provide.labelPosition.${this.groupId}`)
            uni.$off(`provide.type.${this.groupId}`)
            uni.$off(`provide.size.${this.groupId}`)
            uni.$off(`provide.disabled.${this.groupId}`)
        }
    }
}
</script>

<style lang="scss" scoped>
.checkbox {
    position: relative;
    vertical-align: middle;
    .cbx {
        width: 50rpx;
        height: 50rpx;
        border-radius: 8rpx;
        font-size: 32rpx;
        &:not([class*='solid-'])::before {
            border-color: inherit;
        }
        &.sm {
            width: 36rpx;
            height: 36rpx;
            font-size: 24rpx;
        }
    }
    &.left {
        flex-direction: row-reverse;
        .label {
            margin-right: 10rpx;
            text-align: left;
        }
    }
    &.right .label {
        margin-left: 10rpx;
        text-align: right;
    }
    .btn.sm {
        font-size: 24rpx;
        padding: 4rpx 6rpx;
    }
}
</style>
